﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Algobox.JuicyLib.TimeSeries
{
    public class OHLCTimesSeriesRecord : BaseTimeSeriesRecord
    {
        double open = 0.0;
        public double Open
        {
            get { lock (this) { return open; } }
            set { lock (this) { open = value; } }
        }

        double close = 0.0;
        public double Close
        {
            get { lock (this) { return close; } }
            set { lock (this) { close = value; } }
        }

        double high = 0.0;
        public double High
        {
            get { lock (this) { return high; } }
            set { lock (this) { high = value; } }
        }

        double low = 0.0;
        public double Low
        {
            get { lock (this) { return low; } }
            set { lock (this) { low = value; } }
        }


        /// <summary>
        /// defaults all to 0 and set IsGapFill flag true
        /// this is for time periods with no data
        /// </summary>
        /// <param name="data"></param>
        public OHLCTimesSeriesRecord()
            : base()
        {
            IsGapFill = true;
        }

        /// <summary>
        /// defaults all to 0 and set IsGapFill flag true
        /// this is for time periods with no data
        /// </summary>
        /// <param name="data"></param>
        public OHLCTimesSeriesRecord(DateTime now)
            : base()
        {
            IsGapFill = true;
            recordTime = now;
        }

        /// <summary>
        /// defaults all but underlying trade record
        /// </summary>
        /// <param name="data"></param>
        public OHLCTimesSeriesRecord(double data) : base(data)
        {
            IsGapFill = false;
            recordValue = data;
            open = data;
            close = data;
            high = data;
            low = data;
        }

        /// <summary>
        /// defaults all but underlying trade record and trade time
        /// </summary>
        /// <param name="data"></param>
        public OHLCTimesSeriesRecord(double data, DateTime now) : base(data,now)
        {
            recordValue = data;
            recordTime = now;
            open = data;
            close = data;
            high = data;
            low = data;
            IsGapFill = false;
        }


        public void SetData(double data)
        {
            lock (this)
            {
                IsGapFill = false;
                recordValue = data;
                open = data;
                close = data;
                high = data;
                low = data;
            }
        }

        /// <summary>
        /// override to implement different coping of fields
        /// </summary>
        /// <returns></returns>
        public OHLCTimesSeriesRecord CreateNewCopy()
        {
            OHLCTimesSeriesRecord clone = new OHLCTimesSeriesRecord(this.recordValue, this.recordTime);
            clone.open = this.open;
            clone.close = this.close;
            clone.high = this.high;
            clone.low = this.low;
            return clone;
        }



        /// <summary>
        /// Calculates the position in a Alpha Grid
        /// </summary>
        public int? GridPosition(int gridSize)
        {
            double percentile = 0;
            int gridElement = 0;

            if (close == 0)
                return null;
            else if (high == low) // which also == close // no change
                percentile = 0.5;
            else if (IsGapFill)
                percentile = 0.5;
            else
                percentile = (close - low) / (high - low);

            double gridPercentage = 1.0 / gridSize;

            for (int i = 1; i <= gridSize; i++)
                if (percentile <= gridPercentage * i)
                {
                    gridElement = i;
                    break;
                }

            return gridElement;
        }


    }
}
